package cn.edu.yzu.scholarship.kit;

import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;

import com.jfinal.kit.JsonKit;

/**
 * Swiss Army Knife 瑞士军刀，一些常用的方法塞进来
 * 
 * @author francis
 */
public class Sak {

	@SuppressWarnings("serial")
	public static String toJsonStr(final Object key, final Object value) {
		return JsonKit.toJson(new HashMap<Object, Object>() {{put(key, value);}});
	}

	public static <K, V> Map<K, V> newHashMap() {
		return new HashMap<K, V>();
	}

	public static <K, V> Map<K, V> newHashMap(K key, V value) {
		Map<K, V> map = new HashMap<K, V>();
		map.put(key, value);
		return map;
	}

	public static <E> ArrayList<E> newArrayList() {
		return new ArrayList<E>();
	}

	public static <E> HashSet<E> newHashSet() {
		return new HashSet<E>();
	}

	public static void createParentDirs(File file) throws IOException {
		checkNotNull(file);
		File parent = file.getCanonicalFile().getParentFile();
		if (parent == null)
			return;

		parent.mkdirs();
		if (!parent.isDirectory()) {
			throw new IOException("Unable to create parent directories of "
					+ file);
		}
	}

	public static <T> T checkNotNull(T reference) {
		if (reference == null) {
			throw new NullPointerException();
		}
		return reference;
	}

	/**
	 * 数字转成人民币，最多支持17位数字（包含小数点以及小数位数）
	 * http://blog.csdn.net/fjfdszj/article/details/4320190
	 */
	public static String toRMB(double value) {
		char[] hunit = { '拾', '佰', '仟' };// 段内位置表示
		char[] vunit = { '万', '亿' }; // 段名表示
		char[] digit = { '零', '壹', '贰', '叁', '肆', '伍', '陆', '柒', '捌', '玖' }; // 数字表示
		long midVal = (long) (value * 100); // 转化成整形
		String valStr = String.valueOf(midVal); // 转化成字符串
		String head = valStr.substring(0, valStr.length() - 2); // 取整数部分
		String rail = valStr.substring(valStr.length() - 2); // 取小数部分
		String prefix = ""; // 整数部分转化的结果
		String suffix = ""; // 小数部分转化的结果

		if (valStr.length() > 17) throw new RuntimeException("数值过大！");// 解决问题1,超过千亿的问题。

		// 处理小数点后面的数
		if (rail.equals("00")) { // 如果小数部分为0
			suffix = "整";
		} else {
			//处理零角,零分发音问题 2010-06-03
			if(rail.charAt(0)!='0') suffix = digit[rail.charAt(0) - '0'] + "角";
			if(rail.charAt(1)!='0') suffix += digit[rail.charAt(1) - '0'] + "分";
		}
		// 处理小数点前面的数
		char[] chDig = head.toCharArray(); // 把整数部分转化成字符数组
		char zero = '0'; // 标志'0'表示出现过0
		byte zeroSerNum = 0; // 连续出现0的次数
		for (int i = 0; i < chDig.length; i++) { // 循环处理每个数字
			int idx = (chDig.length - i - 1) % 4; // 取段内位置
			int vidx = (chDig.length - i - 1) / 4; // 取段位置
			if (chDig[i] == '0') { // 如果当前字符是0
				zeroSerNum++; // 连续0次数递增
				if (zero == '0' && idx != 0) { // 标志 ,连续零，仅读一次零，
					zero = digit[0]; // 解决问题2,当一个零位于第0位时，不输出“零”，仅输出“段名”.
				} else if (idx == 0 && vidx > 0 && zeroSerNum < 4) {
					prefix += vunit[vidx - 1];
					zero = '0';
				}
				continue;
			}
			zeroSerNum = 0; // 连续0次数清零
			if (zero != '0') { // 如果标志不为0,则加上,例如万,亿什么的
				prefix += zero;
				zero = '0';
			}
			// 取到该位对应数组第几位。
			int position = chDig[i] - '0';
			if (!(position == 1 && i == 0 && idx == 1)) {// 解决问题3 ,即处理10读"拾",而不读"壹拾"
				prefix += digit[position]; // 转化该数字表示
			}

			if (idx > 0) prefix += hunit[idx - 1];// 段内位置表示的值
			
			if (idx == 0 && vidx > 0) prefix += vunit[vidx - 1]; // 段结束位置应该加上段名如万,亿
		}
		
		if (prefix.length() > 0) prefix += '元'; // 如果整数部分存在,则有圆的字样
		
		return prefix + suffix; // 返回正确表示
	}
}
